<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello</title>
</head>
<body>

<div id="root"></div>

<script src="../lib/react.js"></script>
<script src="../lib/react-dom.js"></script>
<script src="../lib/babel-min.js"></script>

<script type="text/babel">
/**
 * this的四种绑定规则：
 *  1.默认绑定，独立执行foo()
 *  2.隐式绑定，被一个对象执行，obj.foo(), this -> obj
 *  3.显式绑定，call/apply/bind, foo.call("aaa") -> String("aaa")
 *  4.new绑定，new Foo(), 创建一个新对象，并且赋值给this
 */
  class App extends React.Component {

    constructor() {
      super();                
      this.state = {
        counter: 100
      }
      // 绑定方式2.提前绑定this
      this.btn1Click = this.btn1Click.bind(this)
    }

    btn1Click() {
      console.log(this);
      this.setState({
        counter: this.state.counter + 1
      })
    }

    //绑定方式3：使用箭头函数，借助ES6的 class fields
    //箭头函数本身没有绑定this，当回调方法使用this时，会自动查询上层作用域的this使用
    btn2Click = () => {
      console.log(this);
      this.setState({
        counter: this.state.counter - 1
      })
    }

    btn3Click() {
      console.log(this);
      this.setState({
        counter: this.state.counter * 2
      })
    }

    render() {
      return (
        <div>
          <h2>当前计数：{this.state.counter}</h2>

          {/* 如果不加bind, 将函数地址传入, 后续进行回调时为默认绑定，而this在非严格模式下指向window，严格模式下为undefined */}
          
          {/* 绑定方式1.使用bind可以明确绑定this */}
          <button onClick={this.btn1Click.bind(this)}>+</button>

          {/* ES6的class fields */}
          <button onClick={this.btn2Click}>-</button>
          
          {/* 绑定方式4：直接传入一个箭头函数(更方便传递参数) - 最常用、最重要*/}
          {/* ES2015 引入了箭头函数，箭头函数不提供自身的 this 绑定（this 的值将保持为闭合词法上下文的值）*/}
          <button onClick={() => this.btn3Click()}>×</button>
        </div>
      )
    }
  }

  const root = ReactDOM.createRoot(document.querySelector("#root"))
  root.render(<App/>)

</script>

</body>
</html>
